package com.example.springboot;


import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;


@RestController
@RequestMapping("/media")
public class MediaController {

    private static final Logger log = LoggerFactory.getLogger(MediaController.class);

    @Autowired
    NonStaticResourceHandler nonStaticResourceHandler;

    @Value("${static.media.dir}")
    String mediaPath;

    @GetMapping("/play/v1/{fileName}")
    public void displayMp4V1(HttpServletRequest request, HttpServletResponse response, @PathVariable("fileName") String fileName) throws IOException {
        File file = new File(mediaPath, fileName);
        if (!file.exists()) {
            response.getOutputStream().close();
            return;
        }
        InputStream inStream = new FileInputStream(file);
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inStream.read(buffer)) != -1) {
            response.getOutputStream().write(buffer, 0, len);
        }
        inStream.close();
        response.getOutputStream().flush();
        response.getOutputStream().close();
    }

    @GetMapping("/play/v2/{fileName}")
    public void displayMp4(HttpServletRequest request, HttpServletResponse response, @PathVariable("fileName") String fileName) throws IOException {
        File file = new File(mediaPath, fileName);
        if (!file.exists()) {
            response.getOutputStream().close();
            return;
        }
        String range = request.getHeader("Range");
        long lenStart = 0;
        if (range != null && range.length() > 7) {
            range = range.substring(6, range.length() - 1);
            lenStart = Long.parseLong(range);
        }
        int size = 102400;
        response.setHeader("Content-Range", "bytes " + lenStart + "-" + ((file.length() - lenStart-2 < size)?file.length()-1:lenStart+size- 1) +"/" + file.length());
        response.setHeader("Content-Type", "video/mp4");
        response.setStatus(HttpStatus.PARTIAL_CONTENT.value());//响应码206表示响应内容为部分数据，需要多次请求
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
        randomAccessFile.seek(lenStart);//设置读取的开始字节数
        //视频每次返回一兆数据
        byte[] buffer = new byte[size];
        int len = randomAccessFile.read(buffer);
        if (len != -1) {
            response.getOutputStream().write(buffer, 0, len);
        }
        randomAccessFile.close();
        response.getOutputStream().flush();
        response.getOutputStream().close();
    }

    /**
     * 读取视频文件
     */
    @GetMapping("/play/v3/{fileName}")
    public void displayMp4V3(HttpServletRequest request, HttpServletResponse response, @PathVariable("fileName") String fileName) throws IOException {
        File file = new File(mediaPath, fileName);
        if (!file.exists()||!file.getName().endsWith(".mp4")) {
            response.getOutputStream().close();
            return;
        }
        String range = request.getHeader("Range");
        log.info("Range:" + range);
        if (range == null) {
            range = "bytes 0";
        }

        log.info("该请求符合断点续传");
        range = range.substring(6);
        String[] arr = range.split("-");
        long lenStart = Long.parseLong(arr[0]);
        long end=0;
        if (arr.length > 1) {
            end = Long.parseLong(arr[1]) ;
        }
        long contentLength=end>0?(end-(lenStart-1)):(file.length()-(lenStart>0?lenStart-1:0));//如果指定范围，就返回范围数据长度，如果没有就返回剩余全部长度
        response.setHeader("Content-Length", String.valueOf(contentLength));
//            response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");//加上会报错，不能用中文
        response.setHeader("Content-Range", "bytes " + lenStart + "-" + (end>0?end:(file.length() - 1)) + "/" + file.length());
        response.setContentType("video/mp4");
        response.setHeader("Accept-Ranges", "bytes");
        response.setStatus(HttpStatus.PARTIAL_CONTENT.value());//响应码206表示响应内容为部分数据，需要多次请求
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
        randomAccessFile.seek(lenStart);//设置读取的开始字节数
        if(end > 0){//客户端指定了范围的数据，那就只给范围数据
            int size= (int) (end-lenStart+1);
            byte[] buffer = new byte[size];
            int len = randomAccessFile.read(buffer);
            if (len != -1) {
                response.getOutputStream().write(buffer, 0, len);
            }
        }else{//没有指定范围
            //视频每次返回一兆数据
            int size = 102400;//1MB
            byte[] buffer = new byte[size];
            int len ;
            while ((len = randomAccessFile.read(buffer)) != -1) {
                response.getOutputStream().write(buffer, 0, len);
            }
        }
        randomAccessFile.close();

        response.getOutputStream().flush();
        response.getOutputStream().close();
    }

    @GetMapping("/play/v4")
    public void videoPreview(HttpServletRequest request, HttpServletResponse response) throws Exception{
        String path = request.getParameter("p");
        Path filePath = Paths.get(path);
        log.info("filePath: {}", filePath);
        if (Files.exists(filePath)) {
            String mimeType = Files.probeContentType(filePath);
            if (!StringUtils.isEmpty(mimeType)) {
                response.setContentType(mimeType);
            }
            request.setAttribute("NON-STATIC-FILE", filePath);
            nonStaticResourceHandler.handleRequest(request, response);
        } else {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        }
    }
}

